home *** CD-ROM | disk | FTP | other *** search
- /* ----------------------------------------------------------------
- * Rule Test Program
- *
- * $Header: /private/postgres/src/test/RCS/testrules.c,v 1.13 1992/06/28 03:48:44 mao Exp $
- * ----------------------------------------------------------------
- */
-
- #include <stdio.h>
- #include "catalog/catname.h"
- #include "access/tupdesc.h"
- #include "access/ftup.h"
- #include "utils/log.h"
- #include "tcop/tcop.h"
- #include "rules/prs2.h"
- #include "rules/prs2stub.h"
- #include "access/heapam.h"
- #include "utils/rel.h"
- #include "executor/executor.h"
-
- /*=======================================================================*/
-
- char * RuleLockToString();
- RuleLock StringToRuleLock();
- EState CreateExecutorState();
-
- /*---- testruleplans.c routines... -----------*/
- List makePlanFromQuery();
- List makePlanFromFile();
- List makePlanFromNLRule();
-
- /*---- testtimer.c routines --------------------*/
- double getTimer();
-
- /*---- routines in this file... ----------------*/
- void TestMain();
- void testTimePlan();
- void testCountPlan();
-
- /*=======================================================================*/
-
- #define MODE_COUNT 10 /* time query mode... */
- #define MODE_TIME 20 /* count tuples mode... */
-
- int TESTRULE_DEBUG_FLAG = 0;
-
- extern int Quiet; /* GLOBAL POSTGRES FLAG */
- extern int ShowStats;
-
- /*=======================================================================
- *
- * run & time some queries....
- *
- * The program takes many options:
- *
- * -db <dbname>
- * This specifies the database name and is proccessed by the routine
- * that calls 'TestMain', so 'TestMain' ignores it
- * -v
- * Run in verbose mode...
- * -Q
- * Run postgres in Quiet mode.
- * -nov
- * TurnOff verbose mode
- * -debug
- * Print a LOT of debugging stuff!
- * -count
- * count the number of tuples generated by the query
- * -time
- * find the time ellapsed to run the query
- * -dummy
- * before running a query, first run a dummy Xact. This will
- * have the side effect of initilalizing the system cache,
- * thus avoiding the significant overhead associated with that...
- * -nodummy
- * Do not run dummy Xacts from now on
- * -f <filename>
- * read the plan information from the given file
- * (see comments in 'makePlanFromFile()' for the file format)
- * -q <query_string>
- * run the given query
- * (see also comments in 'makePlanFromString()')
- * -nl <string>
- * make a plan for rule insertion/deletion simulation
- * (see comments in 'makePlanFronNLRule()' for the string format)
- * -rp <string>
- * create a rule plan and add it to pg_prs2plans
- * see comments in 'addRulePlan' for the string format.
- *
- * NOTE:
- * The program loops through all the options and executes them
- * in order. So, it is possible to execute more than one
- * queries ...
- */
-
- void
- TestMain(argc, argv)
- int argc;
- char *argv[];
- {
- int i;
- int verboseFlag, dummyFlag, mode;
- List planInfo;
- mode = MODE_TIME;
- verboseFlag = 0;
- dummyFlag = 0;
-
- for (i=1; i<argc; i++) {
- if (!strcmp(argv[i], "-debug")) {
- TESTRULE_DEBUG_FLAG = 1;
- } else if (!strcmp(argv[i], "-Q")) {
- Quiet = 1;
- } else if (!strcmp(argv[i], "-v")) {
- verboseFlag = 1;
- } else if (!strcmp(argv[i], "-nov")) {
- verboseFlag = 0;
- } else if (!strcmp(argv[i], "-dummy")) {
- dummyFlag = 1;
- } else if (!strcmp(argv[i], "-nodummy")) {
- dummyFlag = 0;
- } else if (!strcmp(argv[i], "-count")) {
- mode = MODE_COUNT;
- } else if (!strcmp(argv[i], "-time")) {
- mode = MODE_TIME;
- } else if (!strcmp(argv[i], "-f")) {
- i++;
- if (i >= argc) {
- fprintf(stderr,
- "%s: option -f must be followed by a file name\n",
- argv[0]);
- exitpg(1);
- }
- if (verboseFlag) {
- printf("+++ (FILE=) %s\n", argv[i]);
- }
- planInfo = makePlanFromFile(argv[i]);
- runPlan(planInfo, mode, dummyFlag, verboseFlag);
- } else if (!strcmp(argv[i], "-q")) {
- i++;
- if (i >= argc) {
- fprintf(stderr,
- "%s: option -q must be followed by a string\n",
- argv[0]);
- exitpg(1);
- }
- if (verboseFlag) {
- printf("+++ (QUERY=) %s\n", argv[i]);
- }
- planInfo = makePlanFromQuery(argv[i]);
- runPlan(planInfo, mode, dummyFlag, verboseFlag);
- } else if (!strcmp(argv[i], "-rp")) {
- i++;
- if (i >= argc) {
- fprintf(stderr,
- "%s: option -rp must be followed by a string\n",
- argv[0]);
- exitpg(1);
- }
- if (verboseFlag) {
- printf("+++ (ADDRPLAN=) %s\n", argv[i]);
- }
- addRulePlan(argv[i], verboseFlag);
- } else if (!strcmp(argv[i], "-nl")) {
- i++;
- if (i >= argc) {
- fprintf(stderr,
- "%s: option -nl must be followed by a string\n",
- argv[0]);
- exitpg(1);
- }
- if (verboseFlag) {
- printf("+++ (NLRULE=) %s\n", argv[i]);
- }
- planInfo = makePlanFromNLRule(argv[i]);
- runPlan(planInfo, mode, dummyFlag, verboseFlag);
- } else if (!strcmp(argv[i], "-db")) {
- /*
- * ignore this option and the following database name...
- */
- i++;
- } else {
- fprintf(stderr, "%s: Illegal option: %s\n", argv[0], argv[i]);
- exitpg(1);
- }
- }/*for*/
- }
-
- /*---------------------------------------------
- *
- * run the plan
- */
- runPlan(planInfo, mode, dummyFlag, verboseFlag)
- List planInfo;
- int mode;
- int dummyFlag;
- int verboseFlag;
- {
- double time;
- int tupleCount;
-
- if (mode == MODE_TIME) {
- testTimePlan(planInfo, dummyFlag, verboseFlag, &time);
- printf("\n");
- printf("=== (time=) %.6f\n", time);
- } else if (mode == MODE_COUNT) {
- testCountPlan(planInfo, dummyFlag, verboseFlag, &time,
- &tupleCount);
- printf("\n");
- printf("=== (tuples=) %d\n", tupleCount);
- printf("=== (time=) %.6f\n", time);
- } else {
- fprintf(stderr,"Illegal mode = %d\n", mode);
- exitpg(1);
- }
- }
-
-
- /*---------------------------------------------
- * testTimePlan
- *
- * Given a query descriptor, execute the corresponding plan and return
- * the time needed for its completion.
- *
- * There are two flags:
- * runDummyXact: it runs a dummy Xact to fill in the system cache
- * to minimize the overhead of the second query.
- * verbose: if true, then print quite a bit of stuff...
- */
- void
- testTimePlan(plans, runDummyXact, verbose, timeP)
- List plans;
- int runDummyXact;
- int verbose;
- double *timeP;
- {
- Portal portal;
- List qDesc;
- LispValue res1, res2, res3;
- EState exState;
- double time;
- int feature;
- List t, planInfo;
-
- /*
- * run a dummy Xact (to fill in sys$$)
- */
- if (runDummyXact) {
- if (verbose) {
- printf("Running dummy Xact...");
- }
- initTimer();
- StartTransactionCommand(portal);
- pg_eval("retrieve (pg_user.all) where pg_user.oid=\"1234\"::oid",
- (char *) NULL, (ObjectId *) NULL, 0);
- CommitTransactionCommand();
- if (verbose) {
- printf("Dummy Xact took = %.6f secs.\n", getTimer());
- }
- }
-
- /*
- * OK now run the plan
- */
- StartTransactionCommand(portal);
-
- ResetUsage();
- initTimer();
- if (verbose) {
- printf("Starting XACT. timer = %.6f\n", getTimer());
- }
-
- foreach (t, plans) {
- planInfo = CAR(t);
-
- feature = CInteger(CAR(planInfo));
- qDesc = CAR(CDR(planInfo));
- exState = CreateExecutorState();
- res1 = ExecMain(qDesc, exState,
- lispCons(lispInteger(EXEC_START), LispNil));
- res2 = ExecMain(qDesc, exState,
- lispCons(lispInteger(feature), LispNil));
- res3 = ExecMain(qDesc, exState,
- lispCons(lispInteger(EXEC_END), LispNil));
- }
- time = getTimer();
- ShowUsage();
- if (verbose) {
- printf("\n+++ (testTimePlan) %.6f (seconds)\n", time);
- }
-
- CommitTransactionCommand();
-
- /*
- * this dummy start + commit has to be there for no apparent reason...
- * (but it *has* to be there, trust me....)
- */
- StartTransactionCommand(portal);
- CommitTransactionCommand();
-
- *timeP = time;
-
- }
- /*----------------------------------------------
- * testCountPlan
- *
- * Read a plan, execute it & count the #of tuples returned
- * (NOTE, it also returns the time needed...)
- *
- * There are two flags:
- * runDummyXact: it runs a dummy Xact to fill in the system cache
- * to minimize the overhead of the second query.
- * verbose: if true, then print quite a bit of stuff...
- */
- void
- testCountPlan(plans, runDummyXact, verbose, timeP, tupleCountP)
- List plans;
- int runDummyXact;
- int verbose;
- double *timeP;
- int *tupleCountP;
- {
- Portal portal;
- List qDesc;
- LispValue res1, res2, res3;
- EState exState;
- double time;
- int feature;
- int nTuples;
- HeapTuple resultTuple;
- TupleTableSlot slot;
- TupleDescriptor tupDesc;
- List t, planInfo;
-
- /*
- * run a dummy Xact (to fill in sys$$)
- */
- if (runDummyXact) {
- if (verbose) {
- printf("Running dummy Xact...");
- }
- initTimer();
- StartTransactionCommand(portal);
- pg_eval("retrieve (pg_user.all)",
- (char *) NULL, (ObjectId *) NULL, 0);
- CommitTransactionCommand();
- if (verbose) {
- printf("Dummy Xact took = %.6f secs.\n", getTimer());
- }
- }
-
- /*
- * OK now run the plan
- */
- StartTransactionCommand(portal);
-
- ResetUsage();
- initTimer();
- if (verbose) {
- printf("Starting XACT. timer = %.6f\n", getTimer());
- }
- nTuples = 0;
-
- foreach (t, plans) {
- planInfo = CAR(t);
-
- feature = EXEC_RETONE;
- qDesc = CAR(CDR(planInfo));
- exState = CreateExecutorState();
- res1 = ExecMain(qDesc, exState,
- lispCons(lispInteger(EXEC_START), LispNil));
- tupDesc = (TupleDescriptor) CADR(res1);
-
- do {
- res2 = ExecMain(qDesc, exState,
- lispCons(lispInteger(feature), LispNil));
- slot = (TupleTableSlot) res2;
- resultTuple = (HeapTuple) ExecFetchTuple(slot);
- if (resultTuple != NULL) {
- nTuples++;
- if (TESTRULE_DEBUG_FLAG) {
- printf("DEBUG: testCountPlan: tuple no %d\n",nTuples);
- debugtup(resultTuple, tupDesc);
- }
- }
- } while (resultTuple != NULL);
-
- res3 = ExecMain(qDesc, exState,
- lispCons(lispInteger(EXEC_END), LispNil));
- }
- ShowUsage();
- time = getTimer();
- if (verbose) {
- printf("\n+++ (testCountPlan) %.6f (seconds)\n", time);
- printf("\n+++ (testCountPlan) %d (tuples found)\n", nTuples);
- }
-
- CommitTransactionCommand();
-
- /*
- * this dummy start + commit has to be there for no apparent reason...
- * (but it *has* to be there, trust me....)
- */
- StartTransactionCommand(portal);
- CommitTransactionCommand();
-
- *timeP = time;
- *tupleCountP = nTuples;
-
- }
-